﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

//不能又是异步又是同步，注释的是异步部分的代码

namespace IceDog.SSHConnection.LocalCommand.Components
{
    public class SSHClient : IDisposable
    {
        private readonly Process _process;

        private string _host;
        private int _port;
        private string _username;
        private string _password;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="host">远端主机名</param>
        /// <param name="port">远端端口</param>
        /// <param name="user">登录用户名</param>
        /// <param name="password">登录密码</param>
        public SSHClient(string host, int port, string user, string password)
        {
            _host = host;
            _port = port;
            _username = user;
            _password = password;

            _process = new Process();

            ProcessStartInfo info = _process.StartInfo;
            info.CreateNoWindow = true;//不显示程序窗口
            info.UseShellExecute = false;//不使用操作系统shell启动
            info.RedirectStandardOutput = true;//重定向标准输出流
            info.RedirectStandardInput = true;//重定向标准输入流
            info.RedirectStandardError = true;//重定向标准错误流
            //info.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory

            //默认shell是 linux的

            string shellName = "/bin/bash";
            Encoding encoding = Encoding.UTF8;

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                shellName = "cmd.exe";
                encoding = Encoding.GetEncoding("GBK");
            }   

            //设置三个流的编码
            info.StandardInputEncoding = encoding;
            info.StandardOutputEncoding = encoding;
            info.StandardErrorEncoding = encoding;
            //设置shell
            info.FileName = shellName;
            try
            {
                //启动进程
                bool startResult = _process.Start();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"启动 {shellName} 发生了错误，错误信息："+ex.Message);
            }

            if (!HasInstallSSH())
            {
                throw new Exception("command ssh was not found , please install ssh");
            }
            _process.WaitForExit();
            shellName = "ssh";
            _process.StartInfo.FileName = shellName;
            try
            {
                //启动进程
                bool startResult = _process.Start();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"启动 {shellName} 发生了错误，错误信息：" + ex.Message);
            }
        }
        /// <summary>
        /// 判断是否安装了SSH
        /// </summary>
        /// <returns></returns>
        private bool HasInstallSSH()
        {
            //win: OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
            //linux: OpenSSH_6.6.1p1, OpenSSL 1.0.1e-fips 11 Feb 2013
            var result = Execute("ssh -V");
            bool isOutExist = result.stdout.IndexOf("OpenSSH") > -1 || result.stdout.IndexOf("SSL") > -1;
            bool isErrExist = result.stderr.IndexOf("OpenSSH") > -1 || result.stderr.IndexOf("SSL") > -1;
            return isOutExist || isErrExist;
        }
        
        /// <summary>
        /// 执行命令后直接获取输出
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        public (string stdout,string stderr) Execute(string command)
        {
            _process.StandardInput.WriteLine(command);
            // 前面一个命令不管是否执行成功都执行后面(exit)命令，
            //如果不执行exit命令，后面调用ReadToEnd()方法会假死
            _process.StandardInput.WriteLine("exit");
            //把输入从缓存刷入到要写入的地方
            _process.StandardInput.Flush();
            //获取输出结果
            string outResult = _process.StandardOutput.ReadToEnd();
            string errResult = _process.StandardError.ReadToEnd();
            return (outResult, errResult);
        }

        public string Connecting()
        {
            var result = Execute($"ssh -p {_port} {_username}@{_host}");
            return $"{result.stdout}[sep]{result.stderr}";
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sourceFile">要复制的文件或文件夹，多个文件用空格分隔</param>
        /// <param name="targetDirectory">目标目录</param>
        /// <returns></returns>
        public void ScpCopyTo(string sourceFile,string targetDirectory)
        {
            var result = Execute($"scp -P {_port} -r  {sourceFile} {_username}@{_host}:{targetDirectory}");
            //return result;
            
        }

        public void Dispose()
        {
            _process.WaitForExit();
            _process.Close();
        }
    }
}
